package VideoTools;

import java.awt.Color;
import java.awt.Image;
import java.awt.Point;
import java.awt.image.BufferedImage;


import javax.media.Buffer;
import javax.media.format.VideoFormat;
import javax.media.util.BufferToImage;

import VideoTools.CircleOutOfBoundException.CircleException;

import dimension2.Circle;

public class BufferAnalyse {

	public static int MIN_NUMBER_OF_POINT = 2;
	public static int blueRange = 10;
	public static int redRange = 10;
	public static int greenRange = 10;
	// point and color define by the user.
	private Point p;
	private Color c;
	// buffered image refers to the buffer
	private BufferedImage bI;
	// size of the window 
	public static int SIZE_RADIUS_WINDOWS=50;


	/**
	 * Do nothing
	 */
	public BufferAnalyse(){

	}

	/**
	 * do a new bufferAnalyse Object with the specified color
	 */
	public BufferAnalyse(Color c){
		this.c=c;
	}

	/** do esperance and variance in only one loop.
	 * 	do nothing if the Point we have to follow isn't fill.
	 * @return a circle 
	 * if the color c is null return a circle like this : Circle(-1,new Point(-1,-1))
	 * @throws CircleOutOfBoundException 
	 */
	public Circle Analyse(Image image) throws CircleOutOfBoundException{

		bI = (BufferedImage) image;

		if (c!=null){
			
			// define the borne
			int X_sup = (int) (p.getX()+SIZE_RADIUS_WINDOWS);
			int X_inf = (int) (p.getX()-SIZE_RADIUS_WINDOWS);
			int Y_sup = (int) (p.getY()+SIZE_RADIUS_WINDOWS);
			int Y_inf = (int) (p.getY()-SIZE_RADIUS_WINDOWS);

			int diffX_sup_Max_X=bI.getWidth()-X_sup;
			int diffX_inf_Min_X=X_inf;
			int diffY_sup_Max_Y=bI.getHeight()-Y_sup;
			int diffY_inf_Min_Y=Y_inf;

			if (diffX_sup_Max_X<0){
				X_sup=bI.getWidth();
				X_inf=bI.getWidth()-2*SIZE_RADIUS_WINDOWS;
			}
			if (diffX_inf_Min_X<0){
				X_sup=2*SIZE_RADIUS_WINDOWS;
				X_inf=0;
			}
			if (diffY_sup_Max_Y<0){
				Y_sup=bI.getHeight();
				Y_inf=bI.getHeight()-2*SIZE_RADIUS_WINDOWS;
			}
			if (diffY_inf_Min_Y<0){
				Y_sup=2*SIZE_RADIUS_WINDOWS;
				Y_inf=0;
			}
			

			// esperance
			int w=0;
			int h=0;
			// variance
			int w2=0;
			int h2=0;
			// compteur
			int cpt=0;

			for (int i=X_inf;i<X_sup;i++){
				for (int j=Y_inf;j<Y_sup;j++){
					// detect if the pixel is corresponding to what you wanted to.
					int pixel=bI.getRGB(i, j);
					Color c = new Color(pixel);
					// good test
					if (c.getBlue()>this.c.getBlue()-blueRange && 
							c.getBlue()<this.c.getBlue()+blueRange && 
							c.getRed()>this.c.getRed()-redRange && 
							c.getRed()<this.c.getRed()+redRange && 
							c.getGreen()>this.c.getGreen()-greenRange && 
							c.getGreen()<this.c.getGreen()+greenRange){
						w+=i;
						h+=j;
						w2+=i*i;
						h2+=j*j;
						cpt++;

					}
				}
			}


			if (cpt>MIN_NUMBER_OF_POINT){
				// Esperance
				w/=cpt;
				h/=cpt;

				// Variance
				w2/=cpt;
				h2/=cpt;
				w2-=w*w;
				h2-=h*h;

				int distance = (int) Math.sqrt(w2+h2);
				p = new Point(w,h);
				return new Circle(distance,p);
			}
			throw new CircleOutOfBoundException(CircleException.CircleOutOfBound);
		}
		throw new CircleOutOfBoundException(CircleException.NoCircle);
	}



	/** set the color of the point we have to follow
	 * @param p
	 */
	public void setColorOfSelectedPoint(Point p) {
		if (bI!=null){
			this.p=p;
			this.c=new Color(bI.getRGB((int)p.getX(),(int) p.getY()));
		}
	}
	
	public Color getColor(){
		return c;
	}
	
	public void setColor(Color c){
		this.c=c;
	}
}

